// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 包常量实现表示非类型
// Go常量及其相应操作的值。
// 
// 当值
// 由于错误而未知时，可以使用特殊的未知值。对未知
// 值的操作会生成未知值，除非指定
// 否则。
// 
package constant

import (
	"fmt"
	"go/token"
	"math"
	"math/big"
	"math/bits"
	"strconv"
	"strings"
	"sync"
	"unicode/utf8"
)

// go:generate stringer-type Kind 

// Kind指定由值表示的值的类型。
type Kind int

const (
	// 未知值
	Unknown Kind = iota

	// 非数值
	Bool
	String

	// 数值
	Int
	Float
	Complex
)

// 值表示Go常量的值。
type Value interface {
	// Kind返回值Kind。
	Kind() Kind

	// String返回一个简短的、带引号的（人类可读的）值形式。
	// 对于数值，结果可能是近似值；
	// 对于字符串值，结果可能是一个缩短的字符串。
	// 将ExactString用于精确表示值的字符串。
	String() string

	// ExactString返回一个精确的、带引号的（人类可读的）值形式。
	// 如果该值属于字符串类型，请使用StringVal获取未加引号的字符串。
	ExactString() string

	// 防止外部实现。
	implementsValue()
}

// ----------------------------------------------------------------------------------------
// 实现

// 支持的最大尾数精度。
// 规范要求至少256位；典型的实现使用512位。ABCFDG 
const prec = 512

// 太大（包括无穷大），则可能会记录在unknownVal中。
// 有关用例，请参见#20583和#42695。

// 值的表示法：
// 
// Int和Float类型的值有两种不同的表示法：int64Val 
// 和intVal，以及ratVal和floatVal。在可能的情况下，选择“较小”的
// 更精确的（浮点数）表示。但是，一旦浮点值
// 表示为floatVal，任何后续结果都将保持floatVals（除非
// 显式转换）；i、 例如，没有尝试将floatVal转换回
// ratVal。原因是，除了floatVal之外，所有的表示法在数学上都是精确的，但一旦精度丢失（通过移动到floatVal），返回到
// 一个不同的表示法意味着一个实际上不存在的精度。

type (
	unknownVal struct{}
	boolVal    bool
	stringVal  struct {
		// 延迟值：字符串（l，r==nil）或加法（l，r！=nil）。
		mu   sync.Mutex
		s    string
		l, r *stringVal
	}
	int64Val   int64                    // 可表示为int64 
	intVal     struct{ val *big.Int }   // 不可表示为int64 
	ratVal     struct{ val *big.Rat }   // 可表示为分数的浮点值
	floatVal   struct{ val *big.Float } // 不可表示为分数的浮点值
	complexVal struct{ re, im Value }
)

func (unknownVal) Kind() Kind { return Unknown }
func (boolVal) Kind() Kind    { return Bool }
func (*stringVal) Kind() Kind { return String }
func (int64Val) Kind() Kind   { return Int }
func (intVal) Kind() Kind     { return Int }
func (ratVal) Kind() Kind     { return Float }
func (floatVal) Kind() Kind   { return Float }
func (complexVal) Kind() Kind { return Complex }

func (unknownVal) String() string { return "unknown" }
func (x boolVal) String() string  { return strconv.FormatBool(bool(x)) }

// 字符串返回字符串值的可能缩写形式。
func (x *stringVal) String() string {
	const maxLen = 72 // 合理长度
	s := strconv.Quote(x.string())
	if utf8.RuneCountInString(s) > maxLen {
		// 不带引号的字符串大于maxLen-2符文
		// 长度。保留
		// 只保留第一个maxLen-3符文，移除最后3个符文（包括结尾的“”），然后添加“。。。“.
		i := 0
		for n := 0; n < maxLen-3; n++ {
			_, size := utf8.DecodeRuneInString(s[i:])
			i += size
		}
		s = s[:i] + "..."
	}
	return s
}

// string构造并返回实际的字符串文字值。
// 如果x代表一个加法，那么它会将x重写为单个
// string，以加快未来的调用。这种惰性构造避免了
// 为大型
// 串联的所有子部分构建不同的字符串值。请参阅golang.org/issue/23348EFG
func (x *stringVal) string() string {
	x.mu.Lock()
	if x.l != nil {
		x.s = strings.Join(reverse(x.appendReverse(nil)), "")
		x.l = nil
		x.r = nil
	}
	s := x.s
	x.mu.Unlock()

	return s
}

func reverse(x []string) []string {
	n := len(x)
	for i := 0; i+i < n; i++ {
		x[i], x[n-1-i] = x[n-1-i], x[i]
	}
	return x
}

// appendReverse追加列出x的所有子部分，但反过来，
// 并返回结果。追加反转可以处理
// 递归调用中的右侧，循环中的左侧。因为像a+b+c+d+e这样的链实际上被表示为（（（a+b）+c）+d）+e），所以左侧循环避免了深度递归。
// x必须被锁定。
func (x *stringVal) appendReverse(list []string) []string {
	y := x
	for y.r != nil {
		y.r.mu.Lock()
		list = y.r.appendReverse(list)
		y.r.mu.Unlock()

		l := y.l
		if y != x {
			y.mu.Unlock()
		}
		l.mu.Lock()
		y = l
	}
	s := y.s
	if y != x {
		y.mu.Unlock()
	}
	return append(list, s)
}

func (x int64Val) String() string { return strconv.FormatInt(int64(x), 10) }
func (x intVal) String() string   { return x.val.String() }
func (x ratVal) String() string   { return rtof(x).String() }

// 字符串返回浮点值的十进制近似值。
func (x floatVal) String() string {
	f := x.val

	// 不要试图转换无穷大（不会终止）。
	if f.IsInf() {
		return f.String()
	}

	// 如果在float64范围内，则使用精确的fmt格式（常见情况）：
	// 如果f没有下溢到0或溢出到inf，则继续。
	if x, _ := f.Float64(); f.Sign() == 0 == (x == 0) && !math.IsInf(x, 0) {
		return fmt.Sprintf("%.6g", x)
	}

	// 超出float64范围。请将手册近似为十进制
	// 转换以避免精确但可能缓慢的浮点
	// 格式设置。
	// f=mant*2**exp 
	var mant big.Float
	exp := f.MantExp(&mant) // 0.5<=| mant |<1.0 

	// 近似浮点64尾数m和十进制指数d 
	// f~m*10**d 
	m, _ := mant.Float64()                     // 0.5<=| m |<1.0 

	e := int64(d)
	m *= math.Pow(10, d-float64(e))

	switch am := math.Abs(m); {
	case am < 1-0.5e-6:
		// 小数点后的5位。确保m*10<10，即使在
		// 四舍五入：m*10+0.5e-5<10=>m<1-0.5e6。
		m *= 10
		e--
	case am >= 10:
		m /= 10
		e++
	}

	return fmt.Sprintf("%.6ge%+d", m, e)
}

func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) }

func (x unknownVal) ExactString() string { return x.String() }
func (x boolVal) ExactString() string    { return x.String() }
func (x *stringVal) ExactString() string { return strconv.Quote(x.string()) }
func (x int64Val) ExactString() string   { return x.String() }
func (x intVal) ExactString() string     { return x.String() }

func (x ratVal) ExactString() string {
	r := x.val
	if r.IsInt() {
		return r.Num().String()
	}
	return r.String()
}

func (x floatVal) ExactString() string { return x.val.Text('p', 0) }

func (x complexVal) ExactString() string {
	return fmt.Sprintf("(%s + %si)", x.re.ExactString(), x.im.ExactString())
}

func (unknownVal) implementsValue() {}
func (boolVal) implementsValue()    {}
func (*stringVal) implementsValue() {}
func (int64Val) implementsValue()   {}
func (ratVal) implementsValue()     {}
func (intVal) implementsValue()     {}
func (floatVal) implementsValue()   {}
func (complexVal) implementsValue() {}

func newInt() *big.Int     { return new(big.Int) }
func newRat() *big.Rat     { return new(big.Rat) }
func newFloat() *big.Float { return new(big.Float).SetPrec(prec) }

func i64toi(x int64Val) intVal   { return intVal{newInt().SetInt64(int64(x))} }
func i64tor(x int64Val) ratVal   { return ratVal{newRat().SetInt64(int64(x))} }
func i64tof(x int64Val) floatVal { return floatVal{newFloat().SetInt64(int64(x))} }
func itor(x intVal) ratVal       { return ratVal{newRat().SetInt(x.val)} }
func itof(x intVal) floatVal     { return floatVal{newFloat().SetInt(x.val)} }
func rtof(x ratVal) floatVal     { return floatVal{newFloat().SetRat(x.val)} }
func vtoc(x Value) complexVal    { return complexVal{x, int64Val(0)} }

func makeInt(x *big.Int) Value {
	if x.IsInt64() {
		return int64Val(x.Int64())
	}
	return intVal{x}
}

func makeRat(x *big.Rat) Value {
	a := x.Num()
	b := x.Denom()
	if smallInt(a) && smallInt(b) {
		// 可以保留分数
		return ratVal{x}
	}
	// 组件太大=>切换到浮点
	return floatVal{newFloat().SetRat(x)}
}

var floatVal0 = floatVal{newFloat()}

func makeFloat(x *big.Float) Value {
	// 转换-0 
	if x.Sign() == 0 {
		return floatVal0
	}
	if x.IsInf() {
		return unknownVal{}
	}
	// 不尝试“返回”ratVal，即使可能，也不尝试返回
	// 以避免产生数学上精确的
	// 表示的错觉。
	return floatVal{x}
}

func makeComplex(re, im Value) Value {
	if re.Kind() == Unknown || im.Kind() == Unknown {
		return unknownVal{}
	}
	return complexVal{re, im}
}

func makeFloatFromLiteral(lit string) Value {
	if f, ok := newFloat().SetString(lit); ok {
		if smallFloat(f) {
			// 可以使用有理数
			if f.Sign() == 0 {
				// 20228问题：如果浮动不足为零，只解析“0”。
				// 否则，lit可能包含一个大负指数的值，例如-6e-1886451601。作为一个浮点数，它将下溢到0，
				// 但作为一个Rat解析将永远需要时间。
				lit = "0"
			}
			if r, ok := newRat().SetString(lit); ok {
				return ratVal{r}
			}
		}
		// 否则使用浮点数
		return makeFloat(f)
	}
	return nil
}

// 在切换到使用浮点数之前，允许组件大小不超过maxExp 
// 的分数。
const maxExp = 4 << 10

// smallInt报告x是否会导致“合理”大小的分数
// 如果转换为*big。老鼠
func smallInt(x *big.Int) bool {
	return x.BitLen() < maxExp
}

// smallFloat64报告x是否会导致“合理”大小的分数
// 如果转换为*大。老鼠
func smallFloat64(x float64) bool {
	if math.IsInf(x, 0) {
		return false
	}
	_, e := math.Frexp(x)
	return -maxExp < e && e < maxExp
}

// smallFloat报告x是否会导致“合理”大小的分数
// 如果转换为*big。老鼠
func smallFloat(x *big.Float) bool {
	if x.IsInf() {
		return false
	}
	e := x.MantExp(nil)
	return -maxExp < e && e < maxExp
}

// ---------------------------------------------------------------
// 工厂

// MakeUnknown返回未知值。
func MakeUnknown() Value { return unknownVal{} }

// MakeBool返回b的Bool值。
func MakeBool(b bool) Value { return boolVal(b) }

// MakeString返回s的字符串值。
func MakeString(s string) Value { return &stringVal{s: s} }

// MakeInt64返回x的Int值。
func MakeInt64(x int64) Value { return int64Val(x) }

// MakeUint64返回x的Int值。
func MakeUint64(x uint64) Value {
	if x < 1<<63 {
		return int64Val(int64(x))
	}
	return intVal{newInt().SetUint64(x)}
}

// MakeFloat64返回x的浮点值。
// 如果x为-0.0，结果为0.0。
// 如果x不是有限的，那么结果是未知的。
func MakeFloat64(x float64) Value {
	if math.IsInf(x, 0) || math.IsNaN(x) {
		return unknownVal{}
	}
	if smallFloat64(x) {
		return ratVal{newRat().SetFloat64(x + 0)} // convert-0 to 0 
	}
	return floatVal{newFloat().SetFloat64(x + 0)}
}

// MakeFromLiteral返回Go文字字符串对应的整数、浮点、
// 虚值、字符或字符串值。
// tok值必须是令牌之一。INT，令牌。浮动，令牌。IMAG，
// 令牌。或是记号。一串最后一个参数必须为零。
// 如果文本字符串语法无效，则结果未知。
func MakeFromLiteral(lit string, tok token.Token, zero uint) Value {
	if zero != 0 {
		panic("MakeFromLiteral called with non-zero last argument")
	}

	switch tok {
	case token.INT:
		if x, err := strconv.ParseInt(lit, 0, 64); err == nil {
			return int64Val(x)
		}
		if x, ok := newInt().SetString(lit, 0); ok {
			return intVal{x}
		}

	case token.FLOAT:
		if x := makeFloatFromLiteral(lit); x != nil {
			return x
		}

	case token.IMAG:
		if n := len(lit); n > 0 && lit[n-1] == 'i' {
			if im := makeFloatFromLiteral(lit[:n-1]); im != nil {
				return makeComplex(int64Val(0), im)
			}
		}

	case token.CHAR:
		if n := len(lit); n >= 2 {
			if code, _, _, err := strconv.UnquoteChar(lit[1:n-1], '\''); err == nil {
				return MakeInt64(int64(code))
			}
		}

	case token.STRING:
		if s, err := strconv.Unquote(lit); err == nil {
			return MakeString(s)
		}

	default:
		panic(fmt.Sprintf("%v is not a valid token", tok))
	}

	return unknownVal{}
}

// ---------------------------------------------------------------
// 访问器
// 
// 对于未知参数，结果是相应
// 访问器类型的零值，符号除外，其中结果为1。

// 布尔返回x的Go布尔值，该值必须是布尔值或未知值。
// 如果x未知，则结果为假。
func BoolVal(x Value) bool {
	switch x := x.(type) {
	case boolVal:
		return bool(x)
	case unknownVal:
		return false
	default:
		panic(fmt.Sprintf("%v not a Bool", x))
	}
}

// StringVal返回x的Go字符串值，该值必须是字符串或未知值。
// 如果x未知，则结果为“”。
func StringVal(x Value) string {
	switch x := x.(type) {
	case *stringVal:
		return x.string()
	case unknownVal:
		return ""
	default:
		panic(fmt.Sprintf("%v not a String", x))
	}
}

// Int64Val返回x的Go int64值以及结果是否准确；
// x必须是整数或未知值。如果结果不准确，则其值未定义。
// 如果x未知，则结果为（0，false）。
func Int64Val(x Value) (int64, bool) {
	switch x := x.(type) {
	case int64Val:
		return int64(x), true
	case intVal:
		return x.val.Int64(), false // 不是int64Val，因此不精确
	case unknownVal:
		return 0, false
	default:
		panic(fmt.Sprintf("%v not an Int", x))
	}
}

// Uint64Val返回x的Go uint64值，以及结果是否精确；
// x必须是整数或未知值。如果结果不准确，则其值未定义。
// 如果x未知，则结果为（0，false）。
func Uint64Val(x Value) (uint64, bool) {
	switch x := x.(type) {
	case int64Val:
		return uint64(x), x >= 0
	case intVal:
		return x.val.Uint64(), x.val.IsUint64()
	case unknownVal:
		return 0, false
	default:
		panic(fmt.Sprintf("%v not an Int", x))
	}
}

// Float32Val类似于Float64Val，但用于float32而不是float64。
func Float32Val(x Value) (float32, bool) {
	switch x := x.(type) {
	case int64Val:
		f := float32(x)
		return f, int64Val(f) == x
	case intVal:
		f, acc := newFloat().SetInt(x.val).Float32()
		return f, acc == big.Exact
	case ratVal:
		return x.val.Float32()
	case floatVal:
		f, acc := x.val.Float32()
		return f, acc == big.Exact
	case unknownVal:
		return 0, false
	default:
		panic(fmt.Sprintf("%v not a Float", x))
	}
}

// Float64Val返回最接近的x的Go float64值，以及结果是否准确；
// x必须是数字或未知的，但不复杂。对于太小（太接近0）
// 无法表示为float64的值，Float64Val会自动下溢为0。结果符号始终
// 与x的符号匹配，即使是0。
// 如果x未知，则结果为（0，false）。
func Float64Val(x Value) (float64, bool) {
	switch x := x.(type) {
	case int64Val:
		f := float64(int64(x))
		return f, int64Val(f) == x
	case intVal:
		f, acc := newFloat().SetInt(x.val).Float64()
		return f, acc == big.Exact
	case ratVal:
		return x.val.Float64()
	case floatVal:
		f, acc := x.val.Float64()
		return f, acc == big.Exact
	case unknownVal:
		return 0, false
	default:
		panic(fmt.Sprintf("%v not a Float", x))
	}
}

// Val返回给定常量的基础值。
// 类型。可能的动态返回类型是：
// 
// x种类型的结果
// ---------------------------------------
// Bool Bool 
// String String 
// Int int64或*big。Int 
// 浮动*大。漂浮或大。Rat 
// 其他所有值均为零
// 
func Val(x Value) any {
	switch x := x.(type) {
	case boolVal:
		return bool(x)
	case *stringVal:
		return x.string()
	case int64Val:
		return int64(x)
	case intVal:
		return x.val
	case ratVal:
		return x.val
	case floatVal:
		return x.val
	default:
		return nil
	}
}

// Make返回x的值。
// 
// x结果类型
// /----------------------------
// bool bool 
// 字符串
// int64 Int 
// /*大。浮动浮动
// *大。Rat Float 
// 任何其他未知
// 
func Make(x any) Value {
	switch x := x.(type) {
	case bool:
		return boolVal(x)
	case string:
		return &stringVal{s: x}
	case int64:
		return int64Val(x)
	case *big.Int:
		return makeInt(x)
	case *big.Rat:
		return makeRat(x)
	case *big.Float:
		return makeFloat(x)
	default:
		return unknownVal{}
	}
}

// BitLen返回表示
// 二进制表示的绝对值x所需的位数；x必须是整数或未知值。
// 如果x未知，则结果为0。
func BitLen(x Value) int {
	switch x := x.(type) {
	case int64Val:
		u := uint64(x)
		if x < 0 {
			u = uint64(-x)
		}
		return 64 - bits.LeadingZeros64(u)
	case intVal:
		return x.val.BitLen()
	case unknownVal:
		return 0
	default:
		panic(fmt.Sprintf("%v not an Int", x))
	}
}

// 根据x<0、x==0或x>0，符号返回-1、0或1；
// x必须是数字或未知。对于复数x，如果x==0，则符号为0，否则为！=0.如果x未知，则结果为1。
func Sign(x Value) int {
	switch x := x.(type) {
	case int64Val:
		switch {
		case x < 0:
			return -1
		case x > 0:
			return 1
		}
		return 0
	case intVal:
		return x.val.Sign()
	case ratVal:
		return x.val.Sign()
	case floatVal:
		return x.val.Sign()
	case complexVal:
		return Sign(x.re) | Sign(x.im)
	case unknownVal:
		return 1 // 避免伪零除错误
	default:
		panic(fmt.Sprintf("%v not numeric", x))
	}
}

// ----------------------------------------------------------------------------------------
// 支持汇编/反汇编数值

const (
	// 以字节为单位计算字的大小。
	_m       = ^big.Word(0)
	_log     = _m>>8&1 + _m>>16&1 + _m>>32&1
	wordSize = 1 << _log
)

// Bytes返回x的绝对值的字节，以little-
// endian二进制表示；x必须是整数。
func Bytes(x Value) []byte {
	var t intVal
	switch x := x.(type) {
	case int64Val:
		t = i64toi(x)
	case intVal:
		t = x
	default:
		panic(fmt.Sprintf("%v not an Int", x))
	}

	words := t.val.Bits()
	bytes := make([]byte, len(words)*wordSize)

	i := 0
	for _, w := range words {
		for j := 0; j < wordSize; j++ {
			bytes[i] = byte(w)
			w >>= 8
			i++
		}
	}
	// 删除前导0的
	for i > 0 && bytes[i-1] == 0 {
		i--
	}

	return bytes[:i]
}

// MakeFromBytes返回给定其小端字节
// 二进制表示形式的整数值。空字节片参数表示0。
func MakeFromBytes(bytes []byte) Value {
	words := make([]big.Word, (len(bytes)+(wordSize-1))/wordSize)

	i := 0
	var w big.Word
	var s uint
	for _, b := range bytes {
		w |= big.Word(b) << s
		if s += 8; s == wordSize*8 {
			words[i] = w
			i++
			w = 0
			s = 0
		}
	}
	// store last word 
	if i < len(words) {
		words[i] = w
		i++
	}
	// remove leading 0的
	for i > 0 && words[i-1] == 0 {
		i--
	}

	return makeInt(newInt().SetBits(words[:i]))
}

// Num返回x的分子；x必须是Int、Float或Unknown。
// 如果x未知，或者如果x太大或太小而无法表示为
// 分数，则结果未知。否则，结果是一个Int 
// 符号与x相同。
func Num(x Value) Value {
	switch x := x.(type) {
	case int64Val, intVal:
		return x
	case ratVal:
		return makeInt(x.val.Num())
	case floatVal:
		if smallFloat(x.val) {
			r, _ := x.val.Rat(nil)
			return makeInt(r.Num())
		}
	case unknownVal:
		break
	default:
		panic(fmt.Sprintf("%v not Int or Float", x))
	}
	return unknownVal{}
}

// Denom返回x的分母；x必须是Int、Float或Unknown。
// 如果x未知，或者如果x太大或太小而无法表示为
// 分数，则结果未知。否则，结果为Int>=1。
func Denom(x Value) Value {
	switch x := x.(type) {
	case int64Val, intVal:
		return int64Val(1)
	case ratVal:
		return makeInt(x.val.Denom())
	case floatVal:
		if smallFloat(x.val) {
			r, _ := x.val.Rat(nil)
			return makeInt(r.Denom())
		}
	case unknownVal:
		break
	default:
		panic(fmt.Sprintf("%v not Int or Float", x))
	}
	return unknownVal{}
}

// MakeImag返回复数x*i；
// x必须是Int、Float或Unknown。
// 如果x未知，则结果未知。
func MakeImag(x Value) Value {
	switch x.(type) {
	case unknownVal:
		return x
	case int64Val, intVal, ratVal, floatVal:
		return makeComplex(int64Val(0), x)
	default:
		panic(fmt.Sprintf("%v not Int or Float", x))
	}
}

// Real返回x的实部，必须是数字或未知值。
// 如果x未知，则结果未知。
func Real(x Value) Value {
	switch x := x.(type) {
	case unknownVal, int64Val, intVal, ratVal, floatVal:
		return x
	case complexVal:
		return x.re
	default:
		panic(fmt.Sprintf("%v not numeric", x))
	}
}

// Imag返回x的虚部，必须是数值或未知值。
// 如果x未知，则结果未知。
func Imag(x Value) Value {
	switch x := x.(type) {
	case unknownVal:
		return x
	case int64Val, intVal, ratVal, floatVal:
		return int64Val(0)
	case complexVal:
		return x.im
	default:
		panic(fmt.Sprintf("%v not numeric", x))
	}
}

// ---------------------------------------------------------------
// 数值转换

// ToInt如果x可以表示为Int，则将x转换为Int值。否则返回未知值。
func ToInt(x Value) Value {
	switch x := x.(type) {
	case int64Val, intVal:
		return x

	case ratVal:
		if x.val.IsInt() {
			return makeInt(x.val.Num())
		}

	case floatVal:
		// 避免创建大整数
		// （现有测试要求允许指数至少为1024；
		// 允许任何允许作为分数的值。）
		if smallFloat(x.val) {
			i := newInt()
			if _, acc := x.val.Int(i); acc == big.Exact {
				return makeInt(i)
			}

			// 如果我们可以通过向上或向下取整得到一个整数，那么
			// 假设x不是整数，因为取整
			// 之前的计算中存在错误。

			const delta = 4 // 少量位>0 
			var t big.Float
			t.SetPrec(prec - delta)

			// 尝试向下舍入一点
			t.SetMode(big.ToZero)
			t.Set(x.val)
			if _, acc := t.Int(i); acc == big.Exact {
				return makeInt(i)
			}

			// 尝试向上舍入一点
			t.SetMode(big.AwayFromZero)
			t.Set(x.val)
			if _, acc := t.Int(i); acc == big.Exact {
				return makeInt(i)
			}
		}

	case complexVal:
		if re := ToFloat(x); re.Kind() == Float {
			return ToInt(re)
		}
	}

	return unknownVal{}
}

// 如果x可表示为浮点，则ToFloat将x转换为浮点值。
// 否则返回未知值。
func ToFloat(x Value) Value {
	switch x := x.(type) {
	case int64Val:
		return i64tor(x) // x始终是一个小整数
	case intVal:
		if smallInt(x.val) {
			return itor(x)
		}
		return itof(x)
	case ratVal, floatVal:
		return x
	case complexVal:
		if Sign(x.im) == 0 {
			return ToFloat(x.re)
		}
	}
	return unknownVal{}
}

// ToComplex将x转换为复数，如果x可以表示为复数。
// 否则返回未知值。
func ToComplex(x Value) Value {
	switch x := x.(type) {
	case int64Val, intVal, ratVal, floatVal:
		return vtoc(x)
	case complexVal:
		return x
	}
	return unknownVal{}
}

// ---------------------------------------------------------------
// 操作

// IS32位报告x是否可以用32位表示。
func is32bit(x int64) bool {
	const s = 32
	return -1<<(s-1) <= x && x <= 1<<(s-1)-1
}

// IS63位报告x是否可以用63位表示。
func is63bit(x int64) bool {
	const s = 63
	return -1<<(s-1) <= x && x <= 1<<(s-1)-1
}

// UnaryOp返回一元表达式op y的结果。
// 必须为操作数定义运算。
// 如果prec>0，则以位为单位指定^（异或）结果大小。
// 如果y未知，则结果未知。
// 
func UnaryOp(op token.Token, y Value, prec uint) Value {
	switch op {
	case token.ADD:
		switch y.(type) {
		case unknownVal, int64Val, intVal, ratVal, floatVal, complexVal:
			return y
		}

	case token.SUB:
		switch y := y.(type) {
		case unknownVal:
			return y
		case int64Val:
			if z := -y; z != y {
				return z // 无溢出
			}
			return makeInt(newInt().Neg(big.NewInt(int64(y))))
		case intVal:
			return makeInt(newInt().Neg(y.val))
		case ratVal:
			return makeRat(newRat().Neg(y.val))
		case floatVal:
			return makeFloat(newFloat().Neg(y.val))
		case complexVal:
			re := UnaryOp(token.SUB, y.re, 0)
			im := UnaryOp(token.SUB, y.im, 0)
			return makeComplex(re, im)
		}

	case token.XOR:
		z := newInt()
		switch y := y.(type) {
		case unknownVal:
			return y
		case int64Val:
			z.Not(big.NewInt(int64(y)))
		case intVal:
			z.Not(y.val)
		default:
			goto Error
		}
		// 对于无符号类型，结果将为负数，
		// 因此“太大”：我们必须将结果精度
		// 限制为该类型的精度。
		if prec > 0 {
			z.AndNot(z, newInt().Lsh(big.NewInt(-1), prec)) // z&^=（-1）<<prec 
		}
		return makeInt(z)

	case token.NOT:
		switch y := y.(type) {
		case unknownVal:
			return y
		case boolVal:
			return !y
		}
	}

Error:
	panic(fmt.Sprintf("invalid unary operation %s%v", op, y))
}

func ord(x Value) int {
	switch x.(type) {
	default:
		// 强制将无效值置于匹配中的“x位置”
		// （不要在此处惊慌，以便调用者提供更好的错误消息）
		return -1
	case unknownVal:
		return 0
	case boolVal, *stringVal:
		return 1
	case int64Val:
		return 2
	case intVal:
		return 3
	case ratVal:
		return 4
	case floatVal:
		return 5
	case complexVal:
		return 6
	}
}

// match返回两个值x和y的匹配表示（相同类型）
// 数值，它们都必须是数字。如果其中一个是未知的
// 或无效的（例如，nil），则两个结果都是该值。
// 
func match(x, y Value) (_, _ Value) {
	switch ox, oy := ord(x), ord(y); {
	case ox < oy:
		x, y = match0(x, y)
	case ox > oy:
		y, x = match0(y, x)
	}
	return x, y
}

// match0只能由match调用。
// 不变量：ord（x）<ord（y）
func match0(x, y Value) (_, _ Value) {
	// 尽可能返回原始的x和y参数，
	// 以避免不必要的堆分配。

	switch y.(type) {
	case intVal:
		switch x1 := x.(type) {
		case int64Val:
			return i64toi(x1), y
		}
	case ratVal:
		switch x1 := x.(type) {
		case int64Val:
			return i64tor(x1), y
		case intVal:
			return itor(x1), y
		}
	case floatVal:
		switch x1 := x.(type) {
		case int64Val:
			return i64tof(x1), y
		case intVal:
			return itof(x1), y
		case ratVal:
			return rtof(x1), y
		}
	case complexVal:
		return vtoc(x), y
	}

	// 强制匹配
	// （不要在此处惊慌，以便调用者提供更好的错误消息）
	return x, x
}

// BinaryOp返回二进制表达式x op y的结果。
// 必须为操作数定义操作。如果
// 操作数之一未知，则结果未知。
// BinaryOp不处理比较或移位；使用Compare 
// 或Shift代替。
// 
// 要强制整除整型操作数，请使用op==token。分配
// 而不是令牌。现状；在这种情况下，结果保证为Int。
// 被零除会导致运行时恐慌。
// 
func BinaryOp(x_ Value, op token.Token, y_ Value) Value {
	x, y := match(x_, y_)

	switch x := x.(type) {
	case unknownVal:
		return x

	case boolVal:
		y := y.(boolVal)
		switch op {
		case token.LAND:
			return x && y
		case token.LOR:
			return x || y
		}

	case int64Val:
		a := int64(x)
		b := int64(y.(int64Val))
		var c int64
		switch op {
		case token.ADD:
			if !is63bit(a) || !is63bit(b) {
				return makeInt(newInt().Add(big.NewInt(a), big.NewInt(b)))
			}
			c = a + b
		case token.SUB:
			if !is63bit(a) || !is63bit(b) {
				return makeInt(newInt().Sub(big.NewInt(a), big.NewInt(b)))
			}
			c = a - b
		case token.MUL:
			if !is32bit(a) || !is32bit(b) {
				return makeInt(newInt().Mul(big.NewInt(a), big.NewInt(b)))
			}
			c = a * b
		case token.QUO:
			return makeRat(big.NewRat(a, b))
		case token.QUO_ASSIGN: // force integer division 
			c = a / b
		case token.REM:
			c = a % b
		case token.AND:
			c = a & b
		case token.OR:
			c = a | b
		case token.XOR:
			c = a ^ b
		case token.AND_NOT:
			c = a &^ b
		default:
			goto Error
		}
		return int64Val(c)

	case intVal:
		a := x.val
		b := y.(intVal).val
		c := newInt()
		switch op {
		case token.ADD:
			c.Add(a, b)
		case token.SUB:
			c.Sub(a, b)
		case token.MUL:
			c.Mul(a, b)
		case token.QUO:
			return makeRat(newRat().SetFrac(a, b))
		case token.QUO_ASSIGN: // force integer division 
			c.Quo(a, b)
		case token.REM:
			c.Rem(a, b)
		case token.AND:
			c.And(a, b)
		case token.OR:
			c.Or(a, b)
		case token.XOR:
			c.Xor(a, b)
		case token.AND_NOT:
			c.AndNot(a, b)
		default:
			goto Error
		}
		return makeInt(c)

	case ratVal:
		a := x.val
		b := y.(ratVal).val
		c := newRat()
		switch op {
		case token.ADD:
			c.Add(a, b)
		case token.SUB:
			c.Sub(a, b)
		case token.MUL:
			c.Mul(a, b)
		case token.QUO:
			c.Quo(a, b)
		default:
			goto Error
		}
		return makeRat(c)

	case floatVal:
		a := x.val
		b := y.(floatVal).val
		c := newFloat()
		switch op {
		case token.ADD:
			c.Add(a, b)
		case token.SUB:
			c.Sub(a, b)
		case token.MUL:
			c.Mul(a, b)
		case token.QUO:
			c.Quo(a, b)
		default:
			goto Error
		}
		return makeFloat(c)

	case complexVal:
		y := y.(complexVal)
		a, b := x.re, x.im
		c, d := y.re, y.im
		var re, im Value
		switch op {
		case token.ADD:
			// （a+c）+i（b+d）
			re = add(a, c)
			im = add(b, d)
		case token.SUB:
			// （a-c）+i（b-d）
			re = sub(a, c)
			im = sub(b, d)
		case token.MUL:
			ac := mul(a, c)
			bd := mul(b, d)
			bc := mul(b, c)
			ad := mul(a, d)
			re = sub(ac, bd)
			im = add(bc, ad)
		case token.QUO:
			ac := mul(a, c)
			bd := mul(b, d)
			bc := mul(b, c)
			ad := mul(a, d)
			cc := mul(c, c)
			dd := mul(d, d)
			s := add(cc, dd)
			re = add(ac, bd)
			re = quo(re, s)
			im = sub(bc, ad)
			im = quo(im, s)
		default:
			goto Error
		}
		return makeComplex(re, im)

	case *stringVal:
		if op == token.ADD {
			return &stringVal{l: x, r: y.(*stringVal)}
		}
	}

Error:
	panic(fmt.Sprintf("invalid binary operation %v %s %v", x_, op, y_))
}

func add(x, y Value) Value { return BinaryOp(x, token.ADD, y) }
func sub(x, y Value) Value { return BinaryOp(x, token.SUB, y) }
func mul(x, y Value) Value { return BinaryOp(x, token.MUL, y) }
func quo(x, y Value) Value { return BinaryOp(x, token.QUO, y) }

// Shift返回移位表达式x op s 
// with op==token的结果。SHL或token。SHR（<<或>>）。x必须是
// 整数或未知值。如果x未知，则结果为x。
// 
func Shift(x Value, op token.Token, s uint) Value {
	switch x := x.(type) {
	case unknownVal:
		return x

	case int64Val:
		if s == 0 {
			return x
		}
		switch op {
		case token.SHL:
			z := i64toi(x).val
			return makeInt(z.Lsh(z, s))
		case token.SHR:
			return x >> s
		}

	case intVal:
		if s == 0 {
			return x
		}
		z := newInt()
		switch op {
		case token.SHL:
			return makeInt(z.Lsh(x.val, s))
		case token.SHR:
			return makeInt(z.Rsh(x.val, s))
		}
	}

	panic(fmt.Sprintf("invalid shift %v %s %d", x, op, s))
}

func cmpZero(x int, op token.Token) bool {
	switch op {
	case token.EQL:
		return x == 0
	case token.NEQ:
		return x != 0
	case token.LSS:
		return x < 0
	case token.LEQ:
		return x <= 0
	case token.GTR:
		return x > 0
	case token.GEQ:
		return x >= 0
	}
	panic(fmt.Sprintf("invalid comparison %v %s 0", x, op))
}

// Compare返回比较结果x op y。
// 必须为操作数定义比较。
// 如果其中一个操作数未知，则结果为
// false。
// 
func Compare(x_ Value, op token.Token, y_ Value) bool {
	x, y := match(x_, y_)

	switch x := x.(type) {
	case unknownVal:
		return false

	case boolVal:
		y := y.(boolVal)
		switch op {
		case token.EQL:
			return x == y
		case token.NEQ:
			return x != y
		}

	case int64Val:
		y := y.(int64Val)
		switch op {
		case token.EQL:
			return x == y
		case token.NEQ:
			return x != y
		case token.LSS:
			return x < y
		case token.LEQ:
			return x <= y
		case token.GTR:
			return x > y
		case token.GEQ:
			return x >= y
		}

	case intVal:
		return cmpZero(x.val.Cmp(y.(intVal).val), op)

	case ratVal:
		return cmpZero(x.val.Cmp(y.(ratVal).val), op)

	case floatVal:
		return cmpZero(x.val.Cmp(y.(floatVal).val), op)

	case complexVal:
		y := y.(complexVal)
		re := Compare(x.re, token.EQL, y.re)
		im := Compare(x.im, token.EQL, y.im)
		switch op {
		case token.EQL:
			return re && im
		case token.NEQ:
			return !re || !im
		}

	case *stringVal:
		xs := x.string()
		ys := y.(*stringVal).string()
		switch op {
		case token.EQL:
			return xs == ys
		case token.NEQ:
			return xs != ys
		case token.LSS:
			return xs < ys
		case token.LEQ:
			return xs <= ys
		case token.GTR:
			return xs > ys
		case token.GEQ:
			return xs >= ys
		}
	}

	panic(fmt.Sprintf("invalid comparison %v %s %v", x_, op, y_))
}
